abstract class $MAT{ET<$NFE{ET},VT<$VEC{ET,VT},MT<$MAT{ET,VT,MT}}
****

_
The specification of a general Basic matrix.
_
"ET" is the *element_type* which must be a $NFE, a.k.a. numerical field element.

"VT" is its associated vector type, needed to define matrix-vector operations.

"MT" ought to be the same matrix type as the concrete implementations that subtype from this type.

This appears to be somewhat odd, but it serves to give a concrete type so as to allow proper covariance in arguments. Just as a matrix/ vector multiplication method needs to have a specific vector type to go along with the matrix type, matrix/matrix operations like multiplication need to be defined to accept arguments of the same matrix type as "self". For example, a concrete matrix class implementaion MAT_DC (double complex dense matrix) would need to define "plus(arg:MAT_DC)", allowing one to add a MATDC to another, but not allowing one to add a MAT_DC to a MAT_UT_F (upper triangular). The subtyping clause of MAT_DC would then read like
_
____class_MAT_DC_<_$MAT{CPXD,VEC_DC,MAT_DC}_is_...

In this way, this $MAT{ET,VT,MT} class is less useful for allowing run-time substitutability of many implementations than as a precise specification of responsibilities of its subtypes.
_
However, both Basic and Fancy concrete matrices may subtype from $MAT{*,*,*}.
_
If proven to be useful, more general $MAT{} abstract types above this one that do not have covarying features (and thus be useful for run-time polymorphism) may be written in the future.

_____________________Routine_naming_convention.
_____________________==========================
The idea is that reading the routine name in order ought to generate the actual meaning of the operation.
_
_____A_:=_B{^T}_OP_{s*}C{^T}
_
(brackets denote optional operation.)
_
For A,B,C: if B=self, write nothing. If a matrix argument then write "arg". If transpose is desired append "arg" with "_trans", or just add "trans" if self. If an argument is a vector type then use "vec" instead of "arg".
_
For OP, write "plus" for addition, "minus" for subtraction and "times" for multiplication.
_
If "self" is modified, overall routine name should have "inplace_" in front.
_
If there's a scalar multiplication, insert "scaled_" before the second argument.
_
If the routine modifies data in some reference argument, then "into" denotes the argument that will be changed.
_
_
_
_
Example: A := B^T - C.
_____________B_/=_self,_so_"arg".__Transposed_argument.__"arg_trans".
_____________operation_is_subtraction.__"arg_trans_minus".
_____________another_argument,_so_"arg_trans_minus_arg(arg1,arg2:MT)"
_____________is_the_signature.
_
Example: B := B + s*C^T
_____________Modifies_self.__"inplace_".__B_is_self_so_nothing.
_____________"inplace_".__operation_is_addition.__"inplace_plus".
_____________scalar_multiplication.__"inplace_plus_scaled".
_____________matrix_argument,_transposed._
_____________"inplace_plus_scaled_arg_trans(s:ET,arg:MT)"_
_____________is_the_routine_signature.


Descendants
MATCPX MATD MAT MATCPXD
NUMERIC_MAT{_,_} MAT{_,_}



Public


Features
aget(i,j:INT):ET;
****
_
result := self[i,j];
_
Example: m:MAT_D; s:FLTD := m[1,2];
aset(i,j:INT,s:ET);
****
_
self[i,j] := s;
_
Example: m:MAT_D; m[1,2] := 3.0d0;
col(i:INT):VT;
****
_
result := the i'th column of self into a vector.
_
Example: v ::= m.col(4);
col(i:INT,v:VT);
****
_
Set the i'th col of self to v
_
Example: m.col(4,v);
col_elt!(once col:INT):ET;
**** Yield elements by varying index 1 and holding index 2 at `col'. The elements of a "column" col
contents(arg:MT);
****
_
"array portion of self" := "array portion of arg"
_
Example: m2.contents(m); With syntax extension, m2.contents := m; Synonym for "inplace_contents".
copy:MT;
****
_
result := copy of self. Creates new return value.
_
Example: m2 ::= m.copy;
create(nr,nc:INT):MT;
****
_
result := "new matrix, 'nr' x 'nc'"
_
Example: m ::= #MAT_D(10,4);
create(arg:MT):MT;
****
_
result := "matrix, same size as 'arg',
____________data_initialized_to_*zero*."
_
Example: m2 ::= #MAT_D(m);
create_col_matrix(arg:VT):SAME;
****
_
Create a "column" matrix, an N by 1 matrix with elements of arg, and N the size of arg.

Example: v:VEC_D; m ::= MAT_D::create_col(v);
create_row_matrix(arg:VT):SAME;
****
_
Create a "row" matrix, a 1 by N matrix with elements of arg, and N the size of arg.

Example: v:VEC_D; m ::= MAT_D::create_(row);
diag_elt!:ET;
**** Yield values along the diagonal (square in smaller dimension)
elt!: ET;
**** Yield all elements in storage order, usually column-major for new BLAS compatible matrices.
elt1!(once i1:INT):ET;
**** Yield elements by varying index 2 and holding index 1 at `i1'. The elements of a row "i1" this is the same as row_elt!
elt2!(once i2:INT):ET;
**** Yield elements by varying index 1 and holding index 2 at `i2'. The elements of a "column" i2 this is the same as col_elt!
fits(arg:MT):BOOL;
**** is the total number of elements in 'arg' the same as that in self?
ident:MT;
****
_
result "new matrix same size as self " := "identity matrix"
_
Example: m2 ::= m.id; This is the identity under multiplication, of course.
ind1!:INT;
**** Yield each value of the first index in order. The rows
ind2!:INT;
**** Yield each value of the second index in order. The columns
inds!:TUP{INT,INT};
**** Yield tuples of the indices of self in same order as storage.
inplace_arg_minus_arg(arg1,arg2:MT);
****
_
self := arg1 - arg2
_
Example: a,b,c:MAT_D; c.inplace_arg_minus_arg(a,b);
inplace_arg_minus_arg_trans(arg1,arg2:MT);
****
_
self := arg1 - arg2^T;
_
Example: a,b,c:MAT_D; c.inplace_arg_minus_arg_trans(a,b); Requires: self/=arg2.
inplace_arg_plus_arg(arg1,arg2:MT);
****
_
self := arg1 + arg2
_
Example: a,b,c:MAT_D; c.inplace_arg_plus_arg(a,b);
inplace_arg_plus_arg_trans(arg1,arg2:MT);
****

self := arg1 + arg2^T;
_
Example: a,b,c:MAT_D; c.inplace_arg_plus_arg_trans(a,b); Requires: self/=arg2.
inplace_arg_plus_scaled_arg(arg1:MT,s:ET,arg2:MT);
****
_
self := arg1 + s*arg2;
_
Example: a,b,c:MAT_D; c.inplace_arg_plus_scaled_arg(a,3.1415d0,b);
inplace_arg_plus_scaled_arg_trans(arg1:MT,s:ET,arg2:MT);
****
_
self := arg1 + s*arg2^T;
_
Example: a,b,c:MAT_D; c.inplace_arg_plus_scaled_arg_trans(a,3.1415d0,b);
inplace_arg_times_arg(arg1,arg2:MT);
****
_
self := arg1 * arg2.
_
Example: c ::= #MATD(a); c.inplace_arg_times_arg(a,b);
inplace_arg_times_arg_trans(arg1,arg2:MT);
****
_
self := arg1 * arg2^T;
_
Example: c ::= #MATD(a); c.inplace_arg_times_arg_trans(a,b);
inplace_arg_trans(arg:MT);
****
_
"array portion of self" := "transpose of arg"
_
Example: m2:MAT_D; m.inplace_arg_trans(m2);
_
inplace_arg_trans_minus_arg_trans(arg1,arg2:MT);
****
_
self := arg1^T - arg2^T;
_
Example: a,b,c:MAT_D; c.inplace_arg_trans_minus_arg_trans(a,b); Requires: self /= arg1, self/=arg2.
inplace_arg_trans_plus_arg_trans(arg1,arg2:MT);
****

self := arg1^T + arg2^T;
_
Example: a,b,c:MAT_D; c.inplace_arg_trans_plus_arg_trans(a,b); Requires: self /= arg1, self/=arg2.
inplace_arg_trans_times_arg(arg1,arg2:MT);
****
_
self := arg1^T * arg2;
_
Example: c ::= #MATD(a); c.inplace_arg_trans_times_arg(a,b);
inplace_arg_trans_times_arg_trans(arg1,arg2:MT);
****
_
self := arg1^T * arg2^T;
_
Example: c ::= #MATD(a); c.inplace_arg_trans_times_arg_trans(a,b);
inplace_col_plus_scaled_vec(i:INT,s:ET,v:VT);
****
_
Add "s*v" to ith column of self.
_
Example: m:MAT_D; v:VEC_D; m.inplace_col_plus_scaled_vec(4,2.0,v);
inplace_contents(arg:MT);
****
_
"array portion of self" := "array portion of arg"
_
Example: m2.inplace_contents(m);
inplace_contents_from_function(function:ROUT{INT,INT}:ET);
****

"array portion of self"(i,j) = function(i,j) all i,j
_
Example: fun ::= #ROUT( MY_CLASS::hilbert_elements(_:INT,_:INT) ) m:MAT; m.inplace_contents_from_function(fun)
inplace_diag_elt!(val:ET);
**** Set values along the diagonal (square in smaller dimension)
inplace_elements(s:ET);
****
_
self := s "for all elements" Example: m.inplace_elements(0.0) -- clear matrix.
inplace_elt!(val:ET);
**** Set elements in storage order
inplace_ident;
****
_
"array portion of self" := "identity matrix"
_
Example: m.inplace_ident;
inplace_minus_arg(arg:MT);
****
_
self := self - arg.
_
Example: a,b:MAT_D; a.inplace_minus_arg(b);
inplace_minus_arg_trans(arg:MT);
****
_
result (created) := self - arg^T;
_
Example: a,b,c:MAT_D; c := a.plus_arg_trans(b);
inplace_plus_arg(arg:MT);
****
_
self := self + arg.
_
Example: a,b:MAT_D; a.inplace_plus_arg(b);
inplace_plus_arg_trans(arg:MT);
****
_
self := self + arg^T;
_
Example: a,b,c:MAT_D; c := a.plus_arg_trans(b);
inplace_plus_scaled_arg(s:ET,arg:MT);
****
_
self := self + s*arg;
_
Example: a,b:MAT_D; a.inplace_plus_scaled_arg(3.0d0,b);
inplace_plus_scaled_arg_trans(s:ET,arg:MT);
****
_
self := self + s*arg^T;
_
Example: a,b:MAT_D; a.inplace_plus_scaled_arg_trans(3.0d0,b);
inplace_plus_scaled_vec_times_vec(s:ET,v1,v2:VT);
****

self := self + s*v1*v2^T (Add scaled outer product of v1 and v2 to self. A BLAS operation)
_
Example: covariance_mat:MAT_D; datum:VEC_D;
___________covariance_mat.inplace_plus_scaled_vec_times_vec(1.0/n.fltd,
__________________________datum,datum);
inplace_row(i: INT, v:VT);
****
_
Set ith row of self to "v"
_
Example: v:VEC; m.inplace_row_scaled(v);
inplace_row_plus_scaled_vec(i:INT,s:ET,v:VT);
****
_
Add "s*v" to ith row of self.
_
Example: m:MAT_D; v:VEC_D;
____m.inplace_row_plus_scaled_vec(4,2.0,v);
inplace_scaled_by(s:ET);
****
_
self := self * s;
_
Example: m.inplace_scaled_by(4.0d0);
inplace_scaled_col(s:ET,i:INT);
****
_
Scale the i'th column of self by "s".
_
Example: v:MAT_D; m.scale_col(4,3.1415d0);
inplace_scaled_row(s:ET,i:INT);
****
_
Scale the i'th row of self by "s".
_
Example: v:MAT_D; m.scale_row(4,3.1415d0);
inplace_submatrix_to_arg(lr,ur:INT, lc,uc:INT,arg:MT);
****
_
Set a subsection of self[lr..ur,lc..uc] to the argument.
_
Example: m:MAT_D; m2.submatrix(0,9,0,1,m); Or with syntax extension, m2.submatrix(0,9,0,1) := m;
inplace_swapped(arg:MT);
****
_
Swap contents of self with same sized "arg".
_
Example: m2.swap(m1);
inplace_swapped_col(i:INT,v:VT);
****
_
swap "i"'th column of self with "v".
_
Example: m:MAT_D; v:VEC_D; m.swap_column(4,v);
inplace_swapped_row(i:INT,v:VT);
****
_
swap "i"'th row of self with "v".
_
Example: m:MAT_D; v:VEC_D; m.swap_row(4,v);
inplace_trans;
****
_
"array portion of self " := "transpose of self "
_
Example: m.inplace_trans;
is_eq(arg:MT):BOOL;
**** equal to
is_same_shape(arg:MT):BOOL;
**** true if arg has the same dimensions as self.
is_same_shape_trans(arg:MT):BOOL;
**** true if arg^T has the same dimensions as self.
minus(arg:MT):MT;
****
_
result (created) := self + arg.
_
Example: a,b,c:MAT_D; c := a - b; Sugar for "a - b", synonym for "minus_arg".
minus_arg(arg:MT):MT;
****
_
result (created) := self - arg.
_
Example: a,b,c:MAT_D; c := a - b;
minus_arg_trans(arg:MT):MT;
****
_
result (created) := self - arg^T;
_
Example: a,b,c:MAT_D; c := a.plus_arg_trans(b);
nc:INT;
**** number of columns.
nr:INT;
**** number of rows.
plus(arg:MT):MT;
****
_
result (created) := self + arg.
_
Example: a,b,c:MAT_D; c := a + b; Sugar for "a + b", synonym for "plus_arg".
plus_arg(arg:MT):MT;
****
_
result (created) := self + arg.
_
Example: a,b,c:MAT_D; c := a + b;
plus_arg_trans(arg:MT):MT;
****
_
result (created) := self + arg^T;
_
Example: a,b,c:MAT_D; c := a.plus_arg_trans(b);
plus_scaled_arg(s:ET,arg:MT):MT;
****
_
result := self + s*arg;
_
Example: a,b,c:MAT_D; c := a.plus_scaled_arg(3.0d0,b);
plus_scaled_arg_trans(s:ET,arg:MT):MT;
****
_
result := self + s*arg^T;
_
Example: a,b,c:MAT_D; c := a.plus_scaled_arg_trans(3.0d0,b);
row(i:INT):VT;
****
_
result := "ith row of self as a vector"
_
Example: v ::= m.row(4);
row(i:INT,v:VT);
****
_
Set the i'th row of self to v.
_
Example: v:VEC_D; m.row(4,v); With proposed syntax extension: m.row(4) := v;
row_elt!(once row:INT):ET;
**** Yield elements by varying index 2 and holding index 1 at `row'. The elements of a row "row"
scaled_by(s:ET):MT;
****
_
result (created) := self * s;
_
Example: m2 ::= m * 0.40d0;
_
size: INT;
**** Total number of elements (nr*nc)
size1:INT;
**** First dimension (nr)
size2:INT;
**** Second dimension (nc)
str:STR;
****
_
A string representation of self. Creates return value.
_
submatrix(lr,ur:INT, lc,uc:INT):SAME;
****
_
Result a subsection of self[lr..ur,lc..uc] in a newly created return value.

Example: m:MAT_D; m2 ::= m.submatrix(0,9,0,1); -- m2 is 10 x 2
times(arg:MT):MT;
****
_
result := self * arg.
_
Example: c ::= a * b; Sugar for "a * b"
times_arg_trans(arg:MT):SAME;
****
_
result := self * arg^T
_
Example: c ::= a.times_arg_trans(b);
times_elt(s:ET):MT;
****
_
result (created) := self * s;
_
Example: m2 ::= m * 0.40d0; Sugar for "mat * scalar", synonym for 'scaled_by'.
times_scaled_vec_into_vec(s:ET,arg:VT,dest:VT);
****
_
dest := self * s*arg;
_
Example: a:MAT_D; b,c:VEC_D; a.times_scaled_vec_into_vec(-1.0,
___________b,c);
times_vec(arg:VT):VT;
****
_
result := self * arg;
_
Example: a:MAT_D; b:VEC_D; c:VEC_D:= a * b; Sugar for "a * b"
times_vec_into_vec(arg:VT,dest:VT);
****
_
dest := self * arg;
_
Example: a:MAT_D; b,c:VEC_D; a.times_vec_into_vec(b,c);
trans:MT;
****
_
result (created) := "transpose of self"
_
Example: mt ::= m.trans;
trans_times_arg(arg:MT):SAME;
****
_
result := self^T * arg
_
Example: c ::= a.trans_times_arg(b);
trans_times_arg_trans(arg:MT):SAME;
****
_
result := self^T * arg^T;
_
Example: c ::= a.trans_times_arg_trans(b);
trans_times_scaled_vec_into_vec(s:ET,arg:VT,dest:VT);
****
_
dest := self^T * s*arg;
_
Example: a:MAT_D; b,c:VEC_D; a.trans_times_scaled_vec_ into_vec(-2.0,b,c);
trans_times_vec(arg:VT):VT;
****
_
result := self^T * arg.
_
Example: a:MAT_D; b:VEC_D; c:VEC_D:= a.trans_times_vec(b);
trans_times_vec_into_vec(arg:VT,dest:VT);
****
_
dest := self^T * arg;
_
Example: a:MAT_D; b,c:VEC_D; a.trans_times_vec_into_vec(b,c);

The Sather Home Page